package com.jpm.jrogue
{
	import com.jpm.jrogue.factories.ImageFactory;
	import com.jpm.jrogue.graphics.BaseImage;
	import com.jpm.jrogue.graphics.Tile;
	import com.jpm.jrogue.maps.Map;
	import com.jpm.jrogue.maps.OutsideMap;
	import flash.events.TouchEvent;
	import starling.animation.Juggler;
	import starling.animation.Transitions;
	import starling.core.Starling;
	import starling.display.DisplayObject;
	import starling.display.Image;
	import starling.display.Sprite;
	import starling.events.Event;
	import starling.textures.Texture;
	import flash.display.BitmapData;
	import starling.events.TouchPhase;
	import flash.utils.getTimer;
	
	/**
	 * ...
	 * @author Jonboy
	 */
	public class Game extends Sprite
	{
		public var uiSprite:Sprite = new Sprite();
		public var worldSprite:Sprite = new Sprite();
		public var baseSprite:Sprite = new Sprite();
		public var groundSprite:Sprite = new Sprite();
		public var selectionSprite:Sprite = new Sprite();
		public var objectSprite:Sprite = new Sprite();
		public var selector:Image;
		public var level:Map;
		public var stageWidth:int;
		public var stageHeight:int;
		public var middleWidth:int;
		public var middleHeight:int;
		public var player:Player;
		public var rect:flash.display.Sprite = new flash.display.Sprite();
		private var touchLock1:Boolean = false;
		private var touchLock2:Boolean = false;
		public var juggler:Juggler = Starling.juggler;
		public static var instance:Game;
		
		public function Game()
		{
			instance = this;
			
			if (stage)
			{
				init();
			}
			else
			{
				addEventListener(Event.ADDED_TO_STAGE, init);
			}
		}
		
		public function init():void
		{
			
			ImageFactory.init();
			
			stageWidth = stage.stageWidth;
			stageHeight = stage.stageHeight;
			middleWidth = stageWidth * 0.5;
			middleHeight = stageHeight * 0.5;
			
			removeEventListener(Event.ADDED_TO_STAGE, init);
			groundSprite.touchable = false;
			selectionSprite.touchable = false;
			objectSprite.touchable = false;
			worldSprite.addChild(baseSprite);
			worldSprite.addChild(groundSprite);
			worldSprite.addChild(selectionSprite);
			worldSprite.addChild(objectSprite);
			addChild(worldSprite);
			addChild(uiSprite);
			
			selector = ImageFactory.getImage("SelectorRed");
			selector.x = -100;
			selector.y = -100;
			selectionSprite.addChild(selector);
			
			trace("Building Level");
			level = new OutsideMap();
			
			player = new Player(ImageFactory.getTexture("Race1Fighter3"));
			player.x = middleWidth;
			player.y = middleHeight;
			player.width = 108;
			player.height = 108;
			objectSprite.addChild(player);
			
			trace("Drawing");
			draw();
			
			trace("Drawn");
		
		}
		
		public function draw(xTrans:int = 0, yTrans:int = 0):void
		{
			
			for (var xPos:int = player.xPos - 19; xPos <= player.xPos + 19; xPos++)
			{
				for (var yPos:int = player.yPos - 19; yPos <= player.yPos + 19; yPos++)
				{
					
					if (xPos >= 0 || xPos < level.width || yPos >= 0 || yPos < level.height)
					{
						var tile:Tile = level.map[xPos][yPos];
						var hLimit:int = (tile.xPos - player.xPos + tile.yPos - player.yPos);
						var wLimit:int = (tile.xPos - player.xPos - tile.yPos + player.yPos);
						if (hLimit < -18 || hLimit > 12 || wLimit < -14 || wLimit > 12)
						{
							// Outside of the draw area - remove any tiles present here
							if (tile.baseImage != null)
							{
								baseSprite.removeChild(tile.baseImage);
								objectSprite.removeChild(tile.objectImage);
								tile.baseImage = null;
								tile.objectImage = null;
							}
						}
						else
						{
							// Inside area - draw any new tiles
							var x:int = ((xPos - player.xPos - yPos + player.yPos) * 54) + middleWidth - xTrans;
							var y:int = ((xPos - player.xPos + yPos - player.yPos) * 27) + middleHeight - yTrans;
							
							if (tile.baseImage == null && tile.base != null)
							{
								var baseImage:BaseImage = new BaseImage(tile);
								baseImage.x = x;
								baseImage.y = y;
								baseSprite.addChild(baseImage);
								tile.baseImage = baseImage;
							}
							
							if (tile.objectImage == null && tile.object != null)
							{
								var objectImage:Image = ImageFactory.getImage(tile.object);
								objectImage.x = x;
								objectImage.y = y;
								objectSprite.addChild(objectImage);
								tile.objectImage = objectImage;
							}
						}
					}
				}
			}
		}
		
		public function moveTo(tile:Tile):void
		{
			
			if (tile.isPassable && !touchLock1 && !touchLock2)
			{
				
				touchLock1 = true;
				touchLock2 = true;
				
				var xTrans:int = (player.xPos - tile.xPos - player.yPos + tile.yPos) * 54;
				var yTrans:int = (player.xPos - tile.xPos + player.yPos - tile.yPos) * 27;
				player.xPos = tile.xPos;
				player.yPos = tile.yPos;
				
				draw(xTrans + worldSprite.x, yTrans + worldSprite.y);
				
				// Sort the object sprites to make the object ordering correct for the move...
				if ((xTrans == 54 && yTrans == 27 && level.map[tile.xPos][tile.yPos + 1].objectImage != null) || (xTrans == -54 && yTrans == -27 && level.map[tile.xPos][tile.yPos - 1].objectImage != null))
				{
					objectSprite.sortChildren(sortRightLeft);
				}
				else
				{
					objectSprite.sortChildren(sortLeftRight);
				}
				
				juggler.tween(selector, 0.1, {x: selector.x - xTrans, y: selector.y - yTrans, transition: Transitions.LINEAR});
				
				juggler.tween(player, 0.1, {x: player.x - xTrans, y: player.y - yTrans, transition: Transitions.LINEAR, onComplete: function():void
					{
						touchLock1 = false;
					}});
				
				juggler.tween(worldSprite, 0.1, {x: xTrans + worldSprite.x, y: yTrans + worldSprite.y, transition: Transitions.LINEAR, onComplete: function():void
					{
						touchLock2 = false;
					}});
				
					trace(objectSprite.numChildren + " " + baseSprite.numChildren);
			}
		
		}
		
		public function hover(baseImage:Image):void
		{
			
			selector.x = baseImage.x;
			selector.y = baseImage.y;
		}
		
		private function sortLeftRight(a:DisplayObject, b:DisplayObject):int
		{
			if (a.y == b.y)
			{
				return (a.x - b.x);
			}
			return (a.y - b.y);
		}
		
		private function sortRightLeft(a:DisplayObject, b:DisplayObject):int
		{
			if (a.y == b.y)
			{
				return (b.x - a.x);
			}
			return (a.y - b.y);
		}
	}

}